﻿using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;

using PickGold.Handler;
using PickGold.Arguments;

namespace PickGold.Callers
{
	/// <summary>
	/// 线性辅助处理
	/// </summary>
	public class CAssistantRunner : IDisposable
	{
		private static CAssistantRunner _Value;

		private bool _IsRuning = false;
		private Thread _Thread = null;
		private object _Tag;
		private ManualResetEvent _WaitHandler = null;
		private Queue<IDelegate> _Handlers = new Queue<IDelegate>();

		/// <summary>
		/// 线程错误
		/// </summary>
		public event HErrorEventHandler Error;

		/// <summary>
		/// 默认实例
		/// </summary>
		public static CAssistantRunner Value
		{
			get
			{
				if (CAssistantRunner._Value == null)
					CAssistantRunner._Value = new CAssistantRunner();
				return CAssistantRunner._Value;
			}
		}

		/// <summary>
		/// 创建一个实例
		/// </summary>
		public CAssistantRunner()
		{
			this._WaitHandler = new ManualResetEvent(true);
			this._Thread = new Thread(new ThreadStart(this.Run));
			this._Thread.IsBackground = true;
			this._Thread.Start();
		}

		/// <summary>
		/// 获取用于等待辅助操作完成的 System.Threading.WaitHandle。
		/// </summary>
		public WaitHandle AssistantWaitHandle
		{
			get
			{
				return this._WaitHandler;
			}
		}

		/// <summary>
		/// 获取未处理任务总数
		/// </summary>
		public int Tasks
		{
			get
			{
				if (!Monitor.TryEnter(this._Handlers, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this._Handlers);
				try
				{
					return this._Handlers.Count;
				}
				finally
				{
					Monitor.Exit(this._Handlers);
				}
			}
		}

		/// <summary>
		/// 是否正在处理任务
		/// </summary>
		public bool IsRuning
		{
			get
			{
				return this._IsRuning;
			}
		}

		/// <summary>
		/// 设置或获取存储的附加数据
		/// </summary>
		public object Tag
		{
			set
			{
				this._Tag = value;
			}
			get
			{
				return this._Tag;
			}
		}

		/// <summary>
		/// 添加处理队列
		/// </summary>
		/// <param name="handler">委托</param>
		public void Add(IDelegate handler)
		{
			this.Add(handler, true);
		}

		/// <summary>
		/// 添加处理队列
		/// </summary>
		/// <param name="handler">委托</param>
		/// <param name="start">启动</param>
		public void Add(IDelegate handler, bool start)
		{
			if (this._Thread == null)
				throw new ObjectDisposedException(this.GetType().Name);

			if (!Monitor.TryEnter(this._Handlers, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(this._Handlers);
			try
			{
				if (this._Handlers.Contains(handler))
					return;

				this._Handlers.Enqueue(handler);
			}
			finally
			{
				Monitor.Exit(this._Handlers);
			}
			if (start)
				this._WaitHandler.Set();
		}

		/// <summary>
		/// 启动
		/// </summary>
		public void Start()
		{
			if (this._Thread == null)
				throw new ObjectDisposedException(this.GetType().Name);

			this._WaitHandler.Set();
		}

		/// <summary>
		/// 暂停
		/// </summary>
		public void Pause()
		{
			if (this._Thread == null)
				throw new ObjectDisposedException(this.GetType().Name);

			this._WaitHandler.Reset();
		}

		/// <summary>
		/// 停止并销毁
		/// </summary>
		public void Stop()
		{
			this._Thread = null;
			if (this._WaitHandler != null)
				this._WaitHandler.Set();
			this._WaitHandler = null;
			if (this._Handlers != null)
				this._Handlers.Clear();
			this._Handlers = null;
		}

		/// <summary>
		/// 线程错误
		/// </summary>
		/// <param name="e">错误参数</param>
		protected void OnError(CErrorEventArgs e)
		{
			if (this.Error != null)
			{
				this.Error(this, e);
				return;
			}

			e.ThrowError = false;
		}

		/// <summary>
		/// 运行
		/// </summary>
		protected void Run()
		{
			do
			{
				if (this._WaitHandler == null)
					return;

				this._WaitHandler.WaitOne();
				if (this._Thread == null)
					return;

				IDelegate handler;
				if (!Monitor.TryEnter(this._WaitHandler, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this._WaitHandler);
				try
				{
					if (this._Handlers.Count == 0)
					{
						this._WaitHandler.Reset();
						continue;
					}

					handler = this._Handlers.Dequeue();
				}
				finally
				{
					Monitor.Exit(this._WaitHandler);
				}
				this._IsRuning = true;
				try
				{
					handler.Invoke();
				}
				catch (Exception x)
				{
					Tracker.WriteError(x);
					CErrorEventArgs e = new CErrorEventArgs(handler.Handler.Method);
					e.Error = x;
					this.OnError(e);
				}
				this._IsRuning = false;
			} while (this._Thread != null);
			this._Thread = null;
			this._WaitHandler.Close();
			this._WaitHandler = null;
			this._Handlers.Clear();
			this._Handlers = null;
		}

		#region IDisposable 成员

		/// <summary>
		/// 资源是否已释放
		/// </summary>
		public bool IsDisposed
		{
			get
			{
				if (this._Thread == null)
					return true;

				return false;
			}
		}

		/// <summary>
		/// 销毁
		/// </summary>
		public void Dispose()
		{
			//throw new NotImplementedException();
			this.Stop();
		}

		/// <summary/>
		~CAssistantRunner()
		{
			this.Dispose();
		}

		#endregion
	}
}
